package it.fuesi.expired.api.client.base;

import it.fuesi.expired.api.base.CrudService;
import it.fuesi.expired.helpers.ClassResolverHelper;
import it.fuesi.expired.model.FindParameters;
import it.fuesi.expired.model.base.ErrorModel;
import it.fuesi.expired.model.base.IModel;
import it.fuesi.expired.model.base.ModelCollection;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;

public abstract class ACrudBroker<T extends IModel, C extends ModelCollection<T>> extends AClientBroker implements CrudService<T>{

	public ACrudBroker(String endpoint){
		super(endpoint);
	}
	
	public String getResourceFindUri(){
		return getResourceUri() + "/find";
	}
	
	public T add(T item){
		final HttpEntity<T> request = new HttpEntity<T>(item);
		final ResponseEntity<T> response = execute(getResourceUri(), HttpMethod.POST, request,(Class<T>)item.getClass() );
		return response != null ? response.getBody() : null;	
	}
	
	public T update(T item){
		final HttpEntity<T> request = new HttpEntity<T>(item);
		final ResponseEntity<T> response = execute(getResourceUri(), HttpMethod.PUT, request,(Class<T>)item.getClass() );
		return response != null ? response.getBody() : null;	
	}

	public T get(String _id) {
		Class<T> c = getModelClass();
		final ResponseEntity<T> response = execute(getResourceUri() +"/"+ _id, HttpMethod.GET, null, c);
		return response != null ? response.getBody() : null;
	}

	public C getAll() {
		Class<C> c = getCollectionClass();
		final ResponseEntity<C> response = execute(getResourceUri(), HttpMethod.GET, null, c);
		return response != null ? response.getBody() : null;
	}

	public ErrorModel delete(String _id) {
		final ResponseEntity<ErrorModel> response = execute(getResourceUri() + "/" + _id, HttpMethod.DELETE, null, ErrorModel.class);
		return response != null ? response.getBody() : null;
	}

	public ErrorModel deleteAll() {
		final ResponseEntity<ErrorModel> response = execute(getResourceUri(), HttpMethod.DELETE, null, ErrorModel.class);
		return response != null ? response.getBody() : null;
	}
	
	public C find(FindParameters params){
		if(params == null)
			return getAll();
		final ResponseEntity<C> response = execute(getResourceFindUri() + params.toQueryString(), HttpMethod.GET, null, getCollectionClass());
		return response != null ? response.getBody() : null;
	}
	
	/**
     * Method returns class implementing EntityInterface which was used in class
     * extending AbstractDAO
     *
     * @return Class<T extends EntityInterface>
     */
    public Class<T> getModelClass()
    {
        return (Class<T>) ClassResolverHelper.getTypeArguments(ACrudBroker.class, getClass()).get(0);
    }
    
    public Class<C> getCollectionClass()
    {
        return (Class<C>) ClassResolverHelper.getTypeArguments(ACrudBroker.class, getClass()).get(1);
    }

   
	
}
